home *** CD-ROM | disk | FTP | other *** search
/ Aminet 4 / Aminet 4 - November 1994.iso / aminet / comm / net / amitcp_ups10.lha / upsd.c < prev   
C/C++ Source or Header  |  1993-10-10  |  11KB  |  509 lines

  1. #ifndef lint
  2. static char RCSid[] = "$Header: QD:ups/ups2/RCS/upsd.c,v 1.4 1986/11/19 15:21:52 scooter Exp alph $";
  3. #endif
  4.  
  5. /*
  6.  * upsd - package delivery server
  7.  *
  8.  * upsd is the program that is called by inetd when a ups
  9.  * request is issued.  It will read and write to standard input
  10.  * and standard output.  Here is a description of the ups
  11.  * protocol:
  12.  *
  13.  *     ups            upsd                    type
  14.  *
  15.  *  user_name    ------>        login name of package receiver        String
  16.  *  from_name    ------>        login name of package sender        String
  17.  *  full_name    ------>        full name of package sender        String
  18.  *  message    ------>        mail message to send            String
  19.  *        <-----        0 for OK                Byte
  20.  * For each file:
  21.  *  file_name    ------>        name of file to be delivered        String
  22.  *  file_size    ------>        size of file in bytes            Long
  23.  *        <-----        0 for OK                Byte
  24.  *  file    ------>        file size bytes
  25.  *        <-----        0 for OK                Byte
  26.  *  file_mode    ------>        file mode                Int
  27.  *        <-----        0 for OK                Byte
  28.  *
  29.  * When its all done:
  30.  *  complete    ------>        We're done ('-Done-')            String
  31.  *        <-----        0 for OK                Byte
  32.  *
  33.  * $Author: scooter $
  34.  * $Revision: 1.4 $
  35.  * $Date: 1986/11/19 15:21:52 $
  36.  *
  37.  * $Log: upsd.c,v $
  38.  * Revision 1.4  86/11/19  15:21:52  scooter
  39.  * Changed error severity level from ERR to INFO
  40.  * 
  41.  * Revision 1.3  86/09/19  18:53:37  scooter
  42.  * Added -i option for mail specification.
  43.  * Also added syslog stuff.
  44.  * 
  45.  * Revision 1.2  85/08/21  22:28:11  scooter
  46.  * Release revision: added more complete RCS headers.
  47.  * 
  48.  *
  49.  */
  50.  
  51. #ifdef amigados
  52. #include        "sys.h"
  53. #endif
  54.  
  55. #include    <stdio.h>
  56. #include    <pwd.h>
  57. #include    <grp.h>
  58. #include    <sys/file.h>
  59. #include    <sys/types.h>
  60. #include    <netinet/in.h>
  61. #include    <netdb.h>
  62. #include    <syslog.h>
  63. #include    <string.h>
  64.  
  65. #ifndef amigados
  66. long    atol();
  67. int    atoi();
  68. #else
  69. #include <popen.h>
  70. #include "upsd_protos.h"
  71. #endif
  72.  
  73. char    buffer[BUFSIZ*5];    /* character input buffer */
  74. char    file_name[BUFSIZ];    /* file name */
  75. char    file_path[BUFSIZ];    /* full path to destination */
  76. #ifdef amigados
  77. char    file_path2[BUFSIZ];    /* full path to destination */
  78. #endif
  79. char    user_name[BUFSIZ];    /* Receiver name */
  80. char    from_name[BUFSIZ];    /* Sender name */
  81. char    full_name[BUFSIZ];    /* Full name of sender */
  82. char    file_list[BUFSIZ];    /* List of all files */
  83. long    file_size;        /* number of bytes in file */
  84. int    file_mode;        /* mode of the file */
  85. char    mail_message[BUFSIZ*4];    /* mail message */
  86. int    mcount;            /* number of characters in mail buffer */
  87.  
  88. int    fid;            /* File descriptor for destination */
  89. #ifdef DEBUG
  90. int    debugflag = 1;        /* Debug flag */
  91. #else
  92. int    debugflag = 0;        /* Debug flag */
  93. #endif
  94.  
  95. #ifdef amigados
  96. extern int server_socket;
  97. extern int errno;
  98. #endif
  99.  
  100. int fdin, fdout;
  101.  
  102. main(argc, argv)
  103. int argc;
  104. char **argv;
  105. {
  106.     char *ptr,*tptr,*mptr;
  107.     int f, i, file;
  108.     struct sockaddr_in sin;
  109.     struct hostent *peer;
  110.     struct passwd *pwent;
  111.     int retries = 10;
  112.  
  113. #ifndef amigados
  114.     fdinout = 0;
  115.     fdout = 1;
  116. #else
  117.     fdin = server_socket + S_MAXFH; /* s_socket magic */
  118.     fdout = fdin;
  119. #endif
  120.  
  121.     openlog("upsd",LOG_ODELAY,LOG_DAEMON);
  122.  
  123.     syslog(LOG_DEBUG, "started - test");
  124.  
  125.     if(argc>1 && !strcmp(argv[1], "-d") )
  126.         debugflag++;
  127.  
  128.     if (debugflag)
  129.         syslog(LOG_DEBUG,"started");
  130.  
  131.     i = sizeof (sin);
  132.     if (getpeername(fdin, &sin, &i) < 0)
  133.         syslog(LOG_ERR,"getpeername failed: %m");
  134.  
  135.     if (debugflag)
  136.         syslog(LOG_DEBUG,"Calling gethostbyaddr");
  137.  
  138.     peer = gethostbyaddr((char *)&sin.sin_addr,
  139.         sizeof(sin.sin_addr),sin.sin_family);
  140.  
  141.     buffer[0] = '\0';
  142.     file_list[0] = '\0';
  143.  
  144.     if (debugflag)
  145.         syslog(LOG_DEBUG,"Reading first buffer");
  146.  
  147.     read(fdin, buffer, BUFSIZ*5);  /* fetch receiver and sender names */
  148.  
  149.     if (debugflag)
  150.         syslog(LOG_DEBUG,"receiver/sender/message: %s",buffer);
  151.  
  152.     ptr = buffer;
  153.     while (*ptr != '\n')
  154.         ptr++;
  155.     *ptr++ = NULL;
  156.     strcpy(user_name, buffer);    /* save receiver name */
  157.     tptr = ptr;
  158.     while (*tptr != '\n')
  159.         tptr++;
  160.     *tptr++ = NULL;
  161.     strcpy(from_name, ptr);        /* save sender name */
  162.     mptr = tptr;
  163.     while ((*mptr != '\n') && (*mptr != '\0'))
  164.         mptr++;
  165.     *mptr++ = NULL;
  166.     strcpy (full_name, tptr);    /* save sender's full name */
  167.     strcpy (mail_message, mptr);    /* save the mail message */
  168.  
  169.     /*
  170.      * Check for a valid user
  171.      */
  172. #ifdef amigados
  173.     if(1)
  174.     {
  175.         char *env;
  176.         
  177. #if 1 /* deactivate this to become schizophrenic :-) */
  178.         env = getenv("UPS_USERS");
  179.         if(!env)
  180.         {
  181.         error("Receiver name", "UPS_USERS not set");
  182.         exit(1);
  183.         }
  184.         {
  185.         int l = strlen(user_name);
  186.         char *s;
  187.         int legal=0;
  188.  
  189.         while(s = strstr(env, user_name))
  190.         {
  191.             if(((s == env) || (*(s-1) == ':')) 
  192.             && ((s[l] == '\0') || (s[l] == ':')))
  193.             {
  194.             legal = 1;
  195.             break;
  196.             }
  197.         }
  198.         if(!legal)
  199.         {
  200.             error("Receiver name, Not in UPS_USERS:", user_name);
  201.             exit(1);
  202.         }
  203.         }
  204. #endif
  205.         /* fake password entry */
  206.         pwent = malloc(sizeof(struct passwd));
  207.         memset(pwent, 0, sizeof(struct passwd));
  208.         pwent->pw_passwd = strdup("");
  209.         pwent->pw_shell = strdup("");
  210.         pwent->pw_name = strdup(user_name);
  211.         pwent->pw_gecos = strdup("Amiga OS Power User");
  212.  
  213.         ack();
  214.     }
  215. #else
  216.     if ((pwent = getpwnam(user_name)))
  217.         ack();
  218.     else
  219.     {
  220.         error("Receiver name","No such person");
  221.         exit(1);
  222.     }
  223. #endif
  224.     mcount = strlen (mail_message);
  225.     if (debugflag)
  226.         syslog(LOG_DEBUG,"mail message (%d chars):\n %s", mcount, mail_message);
  227.  
  228.     for (file = 0 ;;)
  229.     {
  230. #ifdef amigados
  231.         int cnt;
  232. #endif
  233.         if ((cnt = read(fdin, buffer, BUFSIZ)) <= 0) {
  234.         error("file name","premature EOF or file read error");
  235.         if (debugflag)
  236.             syslog(LOG_DEBUG,"cnt = %d, errno = %d", cnt, errno);
  237. #ifdef amigados
  238.         if(--retries)
  239.         {
  240.             error("file name", "too many retries");
  241.             break;
  242.         }
  243.         continue;
  244.         }
  245. #ifdef amigados
  246.         retries = 10;
  247. #endif
  248.         strcpy(file_name,buffer);
  249.  
  250.         if (debugflag)
  251.         syslog(LOG_DEBUG,"File name:%s",file_name);
  252.  
  253.  
  254.         /*
  255.          * Are we done??
  256.          */
  257.         if (!strncmp(file_name,"-Done-",6)) break;
  258.  
  259.         if ( (fid = opendest(user_name,file_name,
  260.                  pwent->pw_uid,pwent->pw_gid)) <= 0 )
  261.         {
  262.             continue;
  263.         }
  264.         ack();
  265.  
  266.         if (read(fdin, buffer, BUFSIZ) <= 0) {
  267.             error("file size","premature EOF or file read error");
  268.             if (debugflag)
  269.                 syslog(LOG_DEBUG,"errno = %d", errno);
  270.             continue;
  271.         }
  272.  
  273.         file_size = atol(buffer); /* get number of bytes */
  274.         ack();
  275.  
  276.         copyfile(&file);
  277.  
  278.         if (read(fdin, buffer, BUFSIZ) <= 0) {
  279.             error("file mode","premature EOF or file read error");
  280.             continue;
  281.         }
  282.         file_mode = atoi(buffer);     /* get the file mode */
  283. #ifndef amigados
  284.         file_mode &= 0700;        /* Strip the low order modes */
  285. #else
  286.             /* use unix style modes for transmission to be compatible with
  287.                unix version, we will loose amiga specific bits */
  288.         {
  289.             int ami_mode = 8; /* read per default on */
  290.             
  291.             if(file_mode & 0444)
  292.             ami_mode |= 8;
  293.             if(file_mode & 0222)
  294.             ami_mode |= 4 | 1;
  295.             if(file_mode & 0111)
  296.             ami_mode |= 2;
  297.             file_mode = ami_mode;
  298.         }
  299. #endif        
  300.         if (chmod(file_path,file_mode)) {
  301.             error("file mode","chmod failed");
  302.             continue;
  303.         }
  304.         ack();
  305. #ifndef amigados
  306.         chown(file_path,pwent->pw_uid,pwent->pw_gid);
  307. #endif
  308.  
  309.     }
  310.     ack();
  311.  
  312.     if (file)
  313.         sendmail(from_name,full_name,peer->h_name,
  314.             user_name,file_list,file++,mail_message,mcount);
  315. }
  316.  
  317. /*
  318. copyfile
  319. copyfile will copy file_size many bytes from stdin to a temporarily created
  320. file. The filename will be passed back via buffer.
  321. */
  322.  
  323. copyfile(file)
  324. int *file;
  325. {
  326.     long cnt;                /* file size counter */
  327.     int i;
  328.  
  329.     cnt = file_size;        /* count down input bytes */
  330.     while (cnt > 0) {
  331.         i = read(fdin, buffer, BUFSIZ);
  332.         write(fid, buffer, i);
  333.         cnt -= i;
  334.     }
  335.     close(fid);
  336.  
  337.     ack();
  338.     sprintf(buffer,"%-15s",file_name);
  339.     if (*file%4)
  340.         strcat(file_list," ");
  341.     else
  342.         strcat(file_list,"\n\t");
  343.  
  344.     (*file)++;
  345.     strcat(file_list,buffer);
  346. }
  347.  
  348. /*
  349. error(option, string)
  350. char *option, *string;
  351. This routine is called when some error condition has been encountered.
  352. option contains an identifier message, while string contains the actual
  353. error message. Before message is printed, a non-null character is output
  354. first, then the string error message.
  355. */
  356.  
  357. error(option, string)
  358. char *option, *string;
  359. {
  360.     char buf[BUFSIZ];
  361.  
  362.  
  363.     buf[0] = 1;
  364.     write(fdout, buf, 1);    /* nak */
  365.     sprintf(buf, "upsd: %s: %s\n", option, string);
  366.     write(fdout, buf, strlen(buf)+1);
  367.  
  368.     syslog(LOG_INFO,"error - %s",buf);
  369. }
  370.  
  371.  
  372.  
  373. /*
  374.  * ack()
  375.  * This routine is called to return an OK to the remote host.
  376.  */
  377.  
  378. ack()
  379. {
  380.     buffer[0] = 0;
  381.     write(fdout,buffer,1);
  382. }
  383.  
  384.  
  385.  
  386. /*
  387.  * opendest(name,file)
  388.  * char *name,*file;
  389.  *
  390.  * Open the destination file "file" in UPSDIR/user, creating the
  391.  * file if necessary.
  392.  */
  393.  
  394. int
  395. opendest(name,file,uid,gid)
  396. char *name,*file;
  397. int uid,gid;
  398. {
  399.     int ret;
  400.  
  401. #ifndef amigados
  402.     sprintf(file_path,"%s/%s",UPSDIR,name); /* Form path to directory */
  403. #else
  404.     strmfp(file_path,UPSDIR,name); /* Form path to directory */
  405. #endif
  406.  
  407.     if (access(file_path,F_OK) == (-1))
  408.     {
  409. #ifndef amigados
  410.     mkdir(file_path,0700);
  411.     chown(file_path,uid,gid);
  412. #else
  413.     mkdir(file_path);
  414. #endif
  415.     }
  416.  
  417. #ifndef amigados
  418.     sprintf(file_path,"%s/%s/%s",UPSDIR,name,file);
  419. #else
  420.     strcpy(file_path2, file_path);
  421.     sprintf(file_path,"%s/%s",file_path2,file);
  422. #endif    
  423.  
  424.     if (!access(file_path,F_OK))
  425.     {
  426.     error("file creation","A file by that name has already been sent to that user.");
  427.     return(0);
  428.     } else {
  429. #ifndef amigados
  430.     ret = open(file_path,O_WRONLY|O_CREAT,0600);
  431. #else
  432.     ret = open(file_path,O_WRONLY|O_CREAT);
  433. #endif
  434.     if (ret <= 0)
  435.     {
  436.         sprintf(buffer,"unable to open destination file: %s",
  437.             file_path);
  438.         error("file open",buffer);
  439.         return(0);
  440.     }
  441.     return(ret);
  442.     }
  443. }
  444.  
  445.  
  446.  
  447. /*
  448.  * sendmail(from,full,from_host,to,list,mess,count)
  449.  * char *from,*full,*to,*from_host,*list,*mess;
  450.  * int    count;
  451.  *
  452.  * This routine sends mail to the destination user to inform
  453.  * them that ups files are awaiting them.
  454.  */
  455.  
  456. sendmail(from,full,from_host,to,list,file,mess,count)
  457. char *from,*full,*to,*from_host,*list,*mess;
  458. int file,count;
  459. {
  460.     FILE *send,*popen();
  461.     static char myhost[BUFSIZ];
  462.  
  463. #ifndef amigados
  464.     gethostname(myhost,BUFSIZ);
  465. #else
  466.     if(1)
  467.     {
  468.         char *env;
  469.         
  470.         env = getenv("HOSTNAME");
  471.         if(env)
  472.         strncpy(myhost, env, BUFSIZ);
  473.         else
  474.         strncpy(myhost, "HOSTNAME not set", BUFSIZ);
  475.     }
  476. #endif        
  477.     sprintf(buffer,"%s -f%s@%s -F\"%s\" -t",SENDMAIL,from,from_host,full);
  478.  
  479.     if(debugflag)
  480.         syslog(LOG_DEBUG,"sendmail\n%s",buffer);
  481.  
  482.     send = popen(buffer,"w");
  483.  
  484.     fprintf(send,"To: %s@%s\n",to,myhost);
  485.  
  486.     if(debugflag)
  487.         syslog(LOG_DEBUG,"To: %s@%s",to,myhost);
  488.  
  489.     fprintf(send,"Subject: UPS delivery\n");
  490.     if (file > 1)
  491.         strcpy(buffer,"files");
  492.     else
  493.         strcpy(buffer,"file");
  494.  
  495.     fprintf(send,"I have sent you the following %s using ups:\n",buffer);
  496.     fprintf(send,"%s\n\n",list);
  497.     if (file > 1)
  498.         strcpy(buffer,"these files");
  499.     else
  500.         strcpy(buffer,"this file");
  501.  
  502.     fprintf(send,"To retrieve %s, use the ups command.\n\n\n",buffer);
  503.     if (count)
  504.         fprintf(send,"%s\n",mess);
  505.     else
  506.         fprintf(send,"\n\n\n\n---ups\n");
  507.     pclose(send);
  508. }
  509.